/*qtcoincoin Board client in C++ language
   Copyright (C) 2013 -2014  pierre80

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
/**
 * \file parser.cpp
 * \class parser
 * \brief Parseur xml en carton
 * \author Pierre Jourdain
 * \version 0.4
 * \date 3 Juillet 2013
 * \license GPLV3
 * Ceci est un parseur xml il permet de récuperer le contenu des messages
 */

#include "parser.h"


parser::parser(QObject *parent) :QObject(parent)
{
    //Connection du signal de fin de traitement du fichier vers la fonction d'affichage des posts
    //connect(this,SIGNAL(parse_end()),this,SLOT(affiche_board()));
    connect(this,SIGNAL(end_parse()),this,SLOT(get_content()));

}
/**
 * @brief Ouvre le fichier xml en vue de son parcours par le parseur
 *
 * @param file
 */
void parser::openfile(const QString file)
{

    fichier_xml.setFileName(file);
    fichier_xml.open(QIODevice::ReadOnly|QFile::Text);
    qDebug()<<"fichier ouvert\n";

}

/**
 * @brief On récupère les lignes du fichier xml et on les met dans une qstringlist
 *
 */
void parser::getlines(void)
{

    while(!fichier_xml.atEnd())
    {
        messages.append(fichier_xml.readLine());
    }
}
/**
 * @brief Fermeture du fichier
 *
 */
void parser::closefile(void)
{
    fichier_xml.close();
}
/**
 * @fn void parsefile()
 * @todo https://developer.nokia.com/Community/Wiki/QXmlStreamReader_to_parse_XML_in_Qt
 * @brief On récupère les lignes du fichier xml et on les met dans une qstringlist
 * @return Vide (méthode)
 *
 */
void parser::parsefile(const QString content)
{
    //QString extrapost;
    int end_parse=0;
    data.addData(content);
    while(!data.atEnd()&&end_parse==0)
    {
        //qDebug()<<"recherche du point d'entre xml\n";
        data.readNext();
        //data.readNext();
        if(data.isStartDocument())
        {
            qDebug()<<"point d'entre found \n";
            data.readNext();
            data.readNext();
            //On cherche board et on récupère le non du site et on va a l'élement suivant
            if(data.name() == "board")
            {
                site=data.attributes().value("site").toString();
                //On envoie la valeur a l'exterieur de l'objet afin qu'elle puisse être utilisée par le reste du projet
                emit send_site_value(site);
                qDebug()<<"recherche de post\n";//Debug
                data.readNext();//Lecture de l'élément suivant
                data.readNext();//idem
            }
            //On cherche post et on récupère les donnés des posts
            if(data.name()=="post")
            {
                qDebug()<<"Post Trouvé \n";
                analyse_post(data);
                end_parse=1;

            }

        }
        else
        {
            qDebug()<<"not found\n";

        }
    }
    data.clear();
    emit parse_end(order_posts_in_chrono);

    //Coder la fonction
}

/**
 * @fn void analyse_post(QXmlStreamReader xml)
 * @brief On analyse le post trouvé afin d'en extraire les différents eléments
 * @todo https://developer.nokia.com/Community/Wiki/QXmlStreamReader_to_parse_XML_in_Qt
 * @return Vide (méthode)
 *
 */
void parser::analyse_post(QXmlStreamReader& xml)
{
    //xml->readNext();
    //while(data->isStartElement()==false)
    //data->readNext();
    int start_dected=0;
    int end_ok=0;
    //Si détecte post
    //xml.readNext();

    while(!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() =="post")|!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() =="/post")&&end_ok==0)
    {
        if(xml.tokenType() == QXmlStreamReader::StartElement&&start_dected<100&&!xml.hasError())
        {
            start_dected=start_dected+1;
            horloges.append(xml.attributes().value("time").toString());
            ids.append(xml.attributes().value("id").toString());
            xml.readNext();
            xml.readNext();
            //while(data->isEndElement()==false)
            //data->readNext();
            //qDebug()<<"Recherche de l'ua\n";
            if(xml.name()=="info"&&!xml.hasError())
            {
                //qDebug()<<"ua trouvé\n";
                usersagents.append(xml.readElementText());
                //xml.readNext();
                if(!xml.error())//Si pas d'erreur on cherche l'élement suivant
                {
                    xml.readNext();
                    xml.readNext();
                }
                else
                {
                    //Traitement en cas d'erreur
                    xml.readNext();
                }
            }
            //qDebug()<<"Recherche du message\n";
            if(xml.name()=="message"&&!xml.hasError())
            {
                //qDebug()<<"Message trouvé\n";
                messages.append(xml.readElementText());
                //xml.readNext();
                if(!xml.error())//Si pas d'erreur on cherche l'élement suivant
                {
                    xml.readNext();
                    xml.readNext();
                }
                else
                {
                    //Traitement en cas d'erreur
                    xml.readNext();
                }


            }
            //qDebug()<<"Recherche du login\n";
            if(xml.name()=="login"&&!xml.hasError())
            {
                //qDebug()<<"Login trouvé\n";

                logins.append(xml.readElementText());


                if(!xml.error())//Si pas d'erreur on cherche l'élement suivant
                {
                    xml.readNext();
                    xml.readNext();
                }
                else
                {
                    //Traitement en cas d'erreur
                    xml.readNext();
                }
            }
            else
            {
                xml.readNext();
                //xml.readNext();
                //xml.readNext();

            }

            //xml.readNext();
        }
        if(start_dected<100)
        {
            xml.readNext();
            if(xml.error())
            {
                start_dected=100;
            }
        }


        if(start_dected==100)
        {
            end_ok=1;
        }
        //end_ok=1;

    }
    emit send_users_list(logins,usersagents);
    qDebug()<<"fin de traitement du post \n";
    emit end_parse();
}



/**
 * @fn QString readline(int num)
 * @brief Récupération des infos de la qstringlist a la position n
 * @return Qstring
 *
 */
QString parser::readline(int num)
{
    return messages.at(num);
}
/**
 * @fn QString readua(int num)
 * @brief Récupération de l'ua a la ligne num
 * @return QString
 */
QString parser::readua(int num)
{
    return usersagents.at(num);
}
/**
 * @fn QString readmessages(int num)
 * @brief Récupération de l'ua a la ligne num
 * @return QString
 */
QString parser::readmessage(int num)
{
    return messages.at(num);
}
/**
 * @fn QString affiche_data(int num)
 * @brief On affiche les posts
 * @return QString
 */
QString parser::affiche_data(void)
{
    int z=logins.size()-1;
    nb_users=0;
    i=0;
    QString dataout;
    //if((logins.size())!=0)
    //{
    //for(i=0;num<=z;i++)
    //{
    logins_copy=logins;
    logins_copy.removeDuplicates();

    nb_users=logins_copy.size();
    //Parcours de 0 a z-1
    order_posts_in_chrono=true;
    if(order_posts_in_chrono==false)
    {
        while(i<=z-1)
        {
            dataout.append("<div>");
            dataout.append("<font color=\"Blue\">");
            heures=horloges.at(i).mid(8,2);
            minutes=horloges.at(i).mid(10,2);
            secondes=horloges.at(i).mid(12,2);
            dataout.append(heures.append(":"));
            dataout.append(minutes.append(":"));
            dataout.append(secondes.append(" "));

            if(logins.at(i)==0)
            {
                dataout.append("<font color=\"Green\">");
                if((usersagents.at(i).size())<15)
                {
#if QT_VERSION >= 0x05000
                    dataout.append(usersagents.at(i).toUtf8().prepend("<i>").append("</i>"));
#else
                    dataout.append(usersagents.at(i).toAscii().prepend("<i>").append("</i>"));
#endif
                }
                else if((usersagents.at(i).size())<30)
                {
#if QT_VERSION >= 0x05000
                    dataout.append(usersagents.at(i).toUtf8().mid(0,20).prepend("<i>").append("</i>"));
#else
                    dataout.append(usersagents.at(i).toAscii().mid(0,20).prepend("<i>").append("</i>"));
#endif
                }
                else
                {
                    dataout.append("<i>Anonyme</i>");
                }

            }

            else
            {
                dataout.append("<font color=\"Red\">");
                dataout.append(logins.at(i));
            }
            /*if(i!=z-1)
            {
                if(logins.at(i)!=logins.at(i+1))
                {
                    nb_users=nb_users+1;
                }

            }*/

            dataout.append(" ");

            dataout.append("");
            dataout.append("<font color=\"Black\">");
            // dataout.append("\r");
            dataout.append(messages.at(i));
            dataout.append("</div>");
            i++;
        }
    }
    else
    {
        i=z-1;//On se met sur le dernier élément et on décrémente a partir de celui ci
        while(i>-1)
        {
            dataout.append("<div>");
            dataout.append("<font color=\"Blue\">");
            heures=horloges.at(i).mid(8,2);
            minutes=horloges.at(i).mid(10,2);
            secondes=horloges.at(i).mid(12,2);
            dataout.append(heures.append(":"));
            dataout.append(minutes.append(":"));
            dataout.append(secondes.append(" "));

            if(logins.at(i)==0)
            {
                dataout.append("<font color=\"Green\">");
                if((usersagents.at(i).size())<15)
                {
#if QT_VERSION >= 0x05000
                    dataout.append(usersagents.at(i).toUtf8().prepend("<i>").append("</i>"));
#else
                    dataout.append(usersagents.at(i).toAscii().prepend("<i>").append("</i>"));
#endif
                }
                else if((usersagents.at(i).size())<30)
                {
#if QT_VERSION >= 0x05000
                    dataout.append(usersagents.at(i).toUtf8().mid(0,20).prepend("<i>").append("</i>"));
#else
                    dataout.append(usersagents.at(i).toAscii().mid(0,20).prepend("<i>").append("</i>"));
#endif
                }
                else
                {
                    dataout.append("<i>Anonyme</i>");
                }

            }

            else
            {
                dataout.append("<font color=\"Red\">");
                dataout.append(logins.at(i));
            }
            /*if(i!=z-1)
            {
                if(logins.at(i)!=logins.at(i+1))
                {
                    nb_users=nb_users+1;
                }

            }*/

            dataout.append(" ");

            dataout.append("");
            dataout.append("<font color=\"Black\">");
            // dataout.append("\r");
            dataout.append(messages.at(i));
            dataout.append("</div>");
            i--;
        }
    }


    //}
    //}
    //qDebug()<<dataout;
    //on envoie tout le contenu vers la fenetre principale (ou dans d'autres trucs comme par exemple un système d'archivage)
    emit send_users_number(nb_users);
    //qDebug()<<"Émit du signal avec les données décodées";
    emit send_board_data_decoded(dataout);
    //Debug uniquement
    //qDebug()<<"Sortie\n:"<<dataout;
    return dataout;
}
void parser::access_site_name(void)
{
    emit send_namesite(site);
}
void parser::parse_slot(const QByteArray value)
{
    parsefile(value);
}

void parser::affiche_board(bool ok)
{
    affiche_data();
}
void parser::mask_posts(QStringList list_bak,QStringList messages_list,QStringList users)
{
    //Parcours de la QStringList des users un a un et comparaison avec celle des users a cacher
    int i=0;
    int z=0;//Parcours de la liste des users bloqués
    while(i<users.size())
    {
        while(z<list_bak.size())
        {
            //On vérifie que l'utilisateur se trouve dans les utilisateurs indésirables
#if QT_VERSION >=0x05000
            if(users.at(i).toUtf8()==list_bak.at(z).toUtf8())
            {
                //Si trouvé correspondance on remplace le nom de l'user par pika
                users.at(i).toUtf8()="<i>Gros Lourd</i>";
                //Son message aussi
                messages_list.at(i).toUtf8()="<i>Gros lourdingue bloqué</i> ";
                //horloges_list.at(i)="19700110000000";
            }
            //Pas trouvé on passe au suivant
            z++;//On avance dans la liste des users bloqués

#else
            if(users.at(i).toAscii()==list_bak.at(z).toAscii())
            {
                //Si trouvé correspondance on remplace le nom de l'user par pika
                users.at(i).toAscii()="<i>Gros Lourd</i>";
                //Son message aussi
                messages_list.at(i).toAscii()="<i>Gros lourdingue bloqué</i> ";
                //horloges_list.at(i)="19700110000000";
            }
            //Pas trouvé on passe au suivant
            z++;//On avance dans la liste des users bloqués
#endif
        }

        i++;//Incrément dans la liste
    }

}
/**
 * @fn void get_network_reply(QNetworkReply rep)
 * @brief Récupère la réponse du serveur et la stocke dans la variable reply
 * @return QString
 */
/*void parser::get_network_reply(QNetworkReply)
{
    //reply=rep;
}*/
/**
 * @fn void failback_parser(QString content)
 * @brief Parser en cas de fail des fonctions incluses dans Qt
 * @return vide
 *Ce code est le nouveau parseur des posts
 */
void parser::failback_parser(QString content)
{
    /**
      *
      * @info Met content comme flux a analyser
      * @todo http://www.codeprogress.com/cpp/libraries/qt/showQtExample.php?index=14&key=QXmlSimpleReaderParseXML
      * @todo http://www.digitalfanatics.org/projects/qt_tutorial/fr/chapter09.html
      */
    second_parse=new QXmlInputSource;
    second_parse->setData(content);
    parsing=new QXmlSimpleReader;
    /**
      *
      * @info Parcourt le flux jusqu'a la fin (même si erreurs détéctés)
      */
    parsing->parse(second_parse,true);
}
/**
 * @fn void manual_parser(QString content)
 * @brief Parser en cas de fail des fonctions incluses dans Qt
 * @return vide
 *Ce parser a été écrit pour supporter la tribune de LLG< qui à un backend de merde
 */
void parser::manual_parsing(QString content)
{
    failback_parser(content);
}

void parser::get_plonk_users(QStringList plonkusers)
{
    plonk_liste=plonkusers;
}
void parser::bool_order_post(bool var)
{
    order_posts_in_chrono=var;
}
void parser::get_content_from_http(const QByteArray content)
{
    QString get_data(content);
    //parsefile(get_data);
    parse_content(get_data);
}
void parser::get_content()
{
    emit send_board_data_decoded(affiche_data());
}
/**
 * @fn void parse_content(const QString data_xml);
 * @brief Parser en cas de fail des fonctions incluses dans Qt
 * @return vide
 *Ce parser a été écrit pour supporter la tribune de LLG< qui à un backend de merde
 */
void parser::parse_content(const QString data_xml)
{
    int cmtpe=0;
    domdocument=new QDomDocument;
    domdocument->setContent(data_xml);
    qDebug()<<"On recherche les donnés de la tribune";
    root=domdocument->documentElement();

    /**
      *@info On a trouvé le point de départ
      *
      */
    //if(root.namespaceURI()=="board")
    //{
        site_name_board=root.attribute("site");
        //child=new QDomElement;
        emit send_site_value(site_name_board);
        child=root.firstChild().toElement();
        while(!child.isNull()&&cmtpe<100)
        {
            if(child.tagName()=="post")
            {
                horloges.append(child.attribute("time"));
                ids.append(child.attribute("id"));
                second_child=child.firstChild().toElement();
                while(!second_child.isNull()&&cmtpe<100)
                {
                    if(second_child.tagName()=="info")
                    {
                        usersagents.append(second_child.text());
                        //second_child=second_child.nextSibling().toElement();
                    }
                    if(second_child.tagName()=="message")
                    {

                        messages.append(second_child.text());
                        //second_child=second_child.nextSibling().toElement();
                    }
                    if(second_child.tagName()=="login")
                    {

                        logins.append(second_child.text());
                        //
                    }
                second_child=second_child.nextSibling().toElement();

                }
                emit emit_parsing_state(2);
                cmtpe++;
            }

            else
            {
                qDebug()<<"Fichier incorrect";
                emit emit_parsing_state(4);
            }

        child=child.nextSibling().toElement();
        }

    //}
    emit emit_parsing_state(3);
    emit send_users_list(logins,usersagents);
    emit parse_end(order_posts_in_chrono);
    emit end_parse();

}


parser::~parser()
{
    qDebug()<<"Destruction de la classe parser";
    horloges.clear();
    logins.clear();
    messages.clear();
    usersagents.clear();
    ids.clear();


}
